static int relinquish_memory(
struct domain *d, struct page_list_head *list, unsigned long type)
{
- struct page_info *page, *cur;
+ struct page_info *page;
unsigned long x, y;
int ret = 0;
/* Use a recursive lock, as we may enter 'free_domheap_page'. */
spin_lock_recursive(&d->page_alloc_lock);
- page = page_list_first(list);
- while ( !page_list_is_eol(page, list) )
+ while ( (page = page_list_remove_head(list)) )
{
/* Grab a reference to the page so it won't disappear from under us. */
if ( unlikely(!get_page(page, d)) )
{
/* Couldn't get a reference -- someone is freeing this page. */
- cur = page;
- page = page_list_next(page, list);
- page_list_move_tail(cur, list, &d->arch.relmem_list);
+ page_list_add_tail(page, &d->arch.relmem_list);
continue;
}
break;
case -EAGAIN:
case -EINTR:
+ page_list_add(page, list);
set_bit(_PGT_pinned, &page->u.inuse.type_info);
put_page(page);
goto out;
case 0:
break;
case -EINTR:
+ page_list_add(page, list);
page->u.inuse.type_info |= PGT_validated;
if ( x & PGT_partial )
put_page(page);
ret = -EAGAIN;
goto out;
case -EAGAIN:
+ page_list_add(page, list);
page->u.inuse.type_info |= PGT_partial;
if ( x & PGT_partial )
put_page(page);
}
}
- /* Follow the list chain and /then/ potentially free the page. */
- cur = page;
- page = page_list_next(page, list);
- page_list_move_tail(cur, list, &d->arch.relmem_list);
- put_page(cur);
+ /* Put the page on the list and /then/ potentially free it. */
+ page_list_add_tail(page, &d->arch.relmem_list);
+ put_page(page);
if ( hypercall_preempt_check() )
{
}
}
- page_list_splice_init(&d->arch.relmem_list, list);
+ /* list is empty at this point. */
+ if ( !page_list_empty(&d->arch.relmem_list) )
+ {
+ *list = d->arch.relmem_list;
+ INIT_PAGE_LIST_HEAD(&d->arch.relmem_list);
+ }
out:
spin_unlock_recursive(&d->page_alloc_lock);
{
return page != head->next ? mfn_to_page(page->list.prev) : NULL;
}
-static inline int
-page_list_is_eol(const struct page_info *page,
- const struct page_list_head *head)
-{
- return !page;
-}
static inline void
page_list_add(struct page_info *page, struct page_list_head *head)
{
prev->list.next = page->list.next;
}
}
-static inline void
-page_list_move_tail(struct page_info *page, struct page_list_head *list,
- struct page_list_head *head)
-{
- page_list_del(page, list);
- page_list_add_tail(page, head);
-}
static inline struct page_info *
page_list_remove_head(struct page_list_head *head)
{
return page;
}
-static inline void
-page_list_splice_init(struct page_list_head *list, struct page_list_head *head)
-{
- if ( !page_list_empty(list) )
- {
- if ( head->next )
- head->tail->list.next = page_to_mfn(list->next);
- else
- head->next = list->next;
- head->tail = list->tail;
- INIT_PAGE_LIST_HEAD(list);
- }
-}
#define page_list_for_each(pos, head) \
for ( pos = (head)->next; pos; pos = page_list_next(pos, head) )
struct page_info, list)
# define page_list_next(pg, hd) list_entry((pg)->list.next, \
struct page_info, list)
-# define page_list_is_eol(pg, hd) (&(pg)->list == (hd))
# define page_list_add(pg, hd) list_add(&(pg)->list, hd)
# define page_list_add_tail(pg, hd) list_add_tail(&(pg)->list, hd)
# define page_list_del(pg, hd) list_del(&(pg)->list)
# define page_list_del2(pg, hd1, hd2) list_del(&(pg)->list)
-# define page_list_move_tail(pg, o, n) list_move_tail(&(pg)->list, n)
# define page_list_remove_head(hd) (!page_list_empty(hd) ? \
({ \
struct page_info *__pg = page_list_first(hd); \
list_del(&__pg->list); \
__pg; \
}) : NULL)
-# define page_list_splice_init list_splice_init
# define page_list_for_each(pos, head) list_for_each_entry(pos, head, list)
# define page_list_for_each_safe(pos, tmp, head) \
list_for_each_entry_safe(pos, tmp, head, list)